﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DevExpress.Skins;
using DevExpress.LookAndFeel;
using DevExpress.UserSkins;
using DevExpress.XtraEditors;
using AccountingClient.AccountingServer;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Views.Grid;
using System.Linq;
using DevExpress.XtraEditors.Controls;
using System.Configuration;
using System.Threading;


namespace AccountingClient
{
    public partial class FrmMain : XtraForm
    {
        private string username = "";
        private string password = "";
        private string endpointAddress = new AccountingServicesClient().Endpoint.Address.Uri.AbsoluteUri;
        private bool disableGetSummary = false;

        public AccountingClient.AccountingServer.AccountingServicesClient GetServiceClient()
        {
            AccountingServicesClient result = new AccountingServicesClient();
            result.Endpoint.Address = new System.ServiceModel.EndpointAddress(new Uri(endpointAddress), result.Endpoint.Address.Identity, result.Endpoint.Address.Headers);
            result.ClientCredentials.UserName.UserName = username;
            result.ClientCredentials.UserName.Password = password;
            return result;
        }

        public FrmMain()
        {
            InitializeComponent();
        }
        private readonly BindingList<DTOAccount> accList = new BindingList<DTOAccount>();
        private readonly BindingList<DTOTransaction> tranList = new BindingList<DTOTransaction>();
        private readonly IDictionary<int, string> accNames = new Dictionary<int, string>();
        /// <summary>
        /// Kiểm tra tính hợp lệ của một transaction.
        /// - Phải có phần detail.
        /// - Tổng số debits và credits phải bằng nhau.
        /// </summary>
        /// <param name="transaction">chưa thông tin về một transaction cần kiểm tra</param>
        /// <returns>true nếu thông tin hợp lệ, false nếu không</returns>
        private static bool isTransactionValid(DTOTransaction transaction)
        {
            if (transaction == null || transaction.Details == null)
            {
                return false;
            }
            decimal debits = 0;
            decimal credits = 0;
            foreach (var item in transaction.Details)
            {
                if (item.IsCredit)
                {
                    credits += item.Amount;
                }
                else
                {
                    debits += item.Amount;
                }
            }
            return credits == debits;
        }
        /// <summary>
        /// Xây dựng map (id -> Account name) giúp xác định nhanh tên của một account thông qua id của nó
        /// </summary>
        /// <param name="list">Danh sách các mô tả account</param>
        private void BuildAccoutNameDict(IList<DTOAccount> list)
        {
            accNames.Clear();
            if (list != null)
            {
                foreach (var item in list)
                {
                    accNames.Add(item.Id, item.AccountName);
                }
            }
            try
            {
                viewTransactions.BeginUpdate();
                foreach (var item in tranList)
                {
                    item.DetailsUpdated();
                }
            }
            finally
            {
                viewTransactions.EndUpdate();
            }
        }

        void LoadJournal()
        {
            if (journalDateFrom.EditValue == null || journalDateTo.EditValue == null)
            {
                return;
            }
            DateTime fromDate = (DateTime)journalDateFrom.EditValue;
            DateTime toDate = (DateTime)journalDateTo.EditValue;
            if (fromDate > toDate)
            {
                return;
            }
            LoadJournal(fromDate, toDate);
        }
        void LoadJournal(DateTime fromDate, DateTime toDate)
        {
            try
            {
                gridAccount.BeginUpdate();
                gridTransactions.BeginUpdate();
                using (AccountingServicesClient client = GetServiceClient())
                {
                    accList.Clear();
                    var accounts = client.GetAccountList();
                    foreach (var item in accounts)
                    {
                        accList.Add(item);
                    }

                    tranList.Clear();
                    var transactions = client.GetTransactions(fromDate, toDate);
                    foreach (var item in transactions)
                    {
                        tranList.Add(item);
                        //Truyền map accountId -> accountName, giúp xây dựng Field InvolvedAccount
                        item.SetAccountList(accNames);
                        item.DetailsUpdated();
                    }
                }
                gridAccount.DataSource = accList;
                gridTransactions.DataSource = tranList;
                AccountEditor.DataSource = accList;
            }
            catch (Exception e)
            {
                XtraMessageBox.Show(e.Message, "Loading Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
            }
            finally
            {
                gridAccount.EndUpdate();
                gridTransactions.EndUpdate();
            }
        }

        private void viewAccountList_ValidateRow(object sender, DevExpress.XtraGrid.Views.Base.ValidateRowEventArgs e)
        {
            if (e.Row is DTOAccount)
            {
                DTOAccount acc = e.Row as DTOAccount;
                e.Valid = !string.IsNullOrEmpty(acc.AccountName);
                e.ErrorText = "Account name cannot be emtpy.";
            }
        }

        private void viewAccountList_RowUpdated(object sender, DevExpress.XtraGrid.Views.Base.RowObjectEventArgs e)
        {
            DTOAccount acc = e.Row as DTOAccount;
            if (acc != null)
            {
                using (AccountingServicesClient client = GetServiceClient())
                {
                    //Edit already existing Account
                    if (acc.Id != 0)
                    {
                        client.EditAccount(acc);
                    }
                    // Create a new account
                    else
                    {
                        acc.Id = client.AddAccount(acc.AccountName);
                    }
                }
            }
        }

        private void viewAccountList_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                if (XtraMessageBox.Show("Are you sure you want to delete this account ?", "Delete confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1) == System.Windows.Forms.DialogResult.Yes)
                {
                    int[] indexes = viewAccountList.GetSelectedRows();
                    if (indexes != null)
                    {
                        using (AccountingServer.AccountingServicesClient client = GetServiceClient())
                        {
                            for (int i = 0; i < indexes.Length; i++)
                            {
                                DTOAccount acc = viewAccountList.GetRow(indexes[i]) as DTOAccount;
                                if (acc != null)
                                {
                                    string result = client.RemoveAccount(acc.Id);
                                    if (result == null)
                                    {
                                        viewAccountList.DeleteRow(indexes[i]);
                                    }
                                    else
                                    {
                                        var userChoice = XtraMessageBox.Show(result, "Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                                        switch (userChoice)
                                        {
                                            case DialogResult.Abort:
                                                i = indexes.Length;
                                                break;
                                            case DialogResult.Ignore:
                                                break;
                                            case DialogResult.Retry:
                                                i--;
                                                continue;
                                            default:
                                                break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        private void viewTransactions_MasterRowGetRelationCount(object sender, DevExpress.XtraGrid.Views.Grid.MasterRowGetRelationCountEventArgs e)
        {
            e.RelationCount = 1;
        }

        private void viewTransactions_MasterRowEmpty(object sender, DevExpress.XtraGrid.Views.Grid.MasterRowEmptyEventArgs e)
        {
            if (e.RelationIndex == 0)
            {
                DTOTransaction tran = viewTransactions.GetRow(e.RowHandle) as DTOTransaction;
                if (tran != null)
                {
                    e.IsEmpty = !(tran.Details != null && tran.Details.Count > 0);
                }
            }
        }

        private void viewTransactions_MasterRowGetChildList(object sender, DevExpress.XtraGrid.Views.Grid.MasterRowGetChildListEventArgs e)
        {
            if (e.RelationIndex == 0)
            {
                DTOTransaction tran = viewTransactions.GetRow(e.RowHandle) as DTOTransaction;
                if (tran != null)
                {
                    BindingList<TransactionItem> childList = new BindingList<TransactionItem>() { AllowNew = true, AllowRemove = true, AllowEdit = true };
                    if (tran.Details != null)
                    {
                        foreach (var item in tran.Details)
                        {
                            childList.Add(item);
                        }
                    }
                    e.ChildList = childList;
                }
            }
        }

        private void viewTransactions_MasterRowGetRelationName(object sender, DevExpress.XtraGrid.Views.Grid.MasterRowGetRelationNameEventArgs e)
        {
            if (e.RelationIndex == 0)
            {
                e.RelationName = "Transaction details";
            }
        }

        private void viewTransactions_MasterRowGetRelationDisplayCaption(object sender, DevExpress.XtraGrid.Views.Grid.MasterRowGetRelationNameEventArgs e)
        {
            if (e.RelationIndex == 0)
            {
                e.RelationName = "Transaction details";
            }
        }

        private void viewTransactions_MasterRowGetLevelDefaultView(object sender, DevExpress.XtraGrid.Views.Grid.MasterRowGetLevelDefaultViewEventArgs e)
        {
            if (e.RelationIndex == 0)
            {
                e.DefaultView = viewTransDetails;
            }
        }

        private void viewTransDetails_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e)
        {
            TransactionItem detail = e.Row as TransactionItem;
            if (detail != null)
            {
                if (e.IsGetData)
                {
                    if (e.Column.FieldName == colCredit.FieldName)
                    {
                        e.Value = detail.IsCredit ? detail.Amount : 0;
                    }
                    else if (e.Column.FieldName == colDebit.FieldName)
                    {
                        e.Value = detail.IsCredit ? 0 : detail.Amount;
                    }
                }
                else if (e.IsSetData)
                {
                    if (e.Column.FieldName == colCredit.FieldName || e.Column.FieldName == colDebit.FieldName)
                    {
                        if ((decimal)e.Value > 0)
                        {
                            detail.Amount = (decimal)e.Value;
                            detail.IsCredit = e.Column.FieldName == colCredit.FieldName;
                        }
                    }
                }
            }
        }

        private void viewTransDetails_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
        {
            if (e.Column.FieldName == colDebit.FieldName || e.Column.FieldName == colCredit.FieldName)
            {
                if (e.Value != null && (decimal)e.Value == 0)
                {
                    e.DisplayText = "";
                }
            }
        }

        /// <summary>
        /// Re-validate the assocaited transaction of transaction details.
        /// </summary>
        /// <param name="view">the GridView presenting the transaction detail data.</param>
        private void RevalidateTransaction(GridView view)
        {
            DTOTransaction tran = view.SourceRow as DTOTransaction;
            viewTransactions.ClearColumnErrors();
            if (!isTransactionValid(tran))
            {
                viewTransactions.SetColumnError(null, "Total debit and total credit are not equal.");
            }
            else
            {
                tran.DetailsUpdated();
                // The related transaction should be updated.
                viewTransactions_RowUpdated(viewTransactions, new DevExpress.XtraGrid.Views.Base.RowObjectEventArgs(view.SourceRowHandle, view.SourceRow));
            }
        }
        private void viewTransDetails_RowUpdated(object sender, DevExpress.XtraGrid.Views.Base.RowObjectEventArgs e)
        {
            GridView view = sender as GridView;
            if (view != null)
            {
                DTOTransaction tran = view.SourceRow as DTOTransaction;
                if (tran != null)
                {
                    TransactionItem item = e.Row as TransactionItem;
                    // Add to detail of transaction if the updated row is a new row.
                    if (tran.Details == null)
                    {
                        tran.Details = new List<TransactionItem>();
                        tran.Details.Add(item);
                    }
                    else
                    {
                        if (!tran.Details.Contains(item))
                        {
                            tran.Details.Add(item);
                        }
                    }
                    //Re-validate the transaction
                    RevalidateTransaction(view);
                }
            }
        }

        private void viewTransDetails_ValidateRow(object sender, DevExpress.XtraGrid.Views.Base.ValidateRowEventArgs e)
        {
            GridView view = sender as GridView;
            if (view != null)
            {
                TransactionItem row = e.Row as TransactionItem;
                if (row != null)
                {
                    //Checking for existing of account.
                    var query = from a in accList
                                where a.Id == row.AccountId
                                select a;
                    DTOAccount acc = query.SingleOrDefault();
                    if (acc == null)
                    {
                        e.Valid = false;
                        e.ErrorText = "Account cannot be empty.";
                        return;
                    }
                    // Checking for duplicate account in detail
                    BindingList<TransactionItem> data = view.DataSource as BindingList<TransactionItem>;
                    if (data != null)
                    {
                        var duplicateQuery = from a in data
                                             where a.AccountId == acc.Id
                                             select a;
                        if (duplicateQuery.Count() > 1)
                        {
                            e.Valid = false;
                            e.ErrorText = "The account of each detail in one transaction must be unique.";
                        }
                    }
                }
            }
        }

        private void viewTransactions_RowUpdated(object sender, DevExpress.XtraGrid.Views.Base.RowObjectEventArgs e)
        {
            DTOTransaction tran = e.Row as DTOTransaction;
            if (tran != null)
            {
                using (AccountingServer.AccountingServicesClient client = GetServiceClient())
                {
                    if (tran.Id > 0)
                    {
                        string mess = client.EditTransaction(tran);
                        if (mess != null)
                        {
                            viewTransactions.SetColumnError(null, mess);
                        }
                    }
                    else
                    {
                        int id = client.InsertTransaction(tran);
                        if (id > 0)
                        {
                            tran.Id = id;
                        }
                        else
                        {
                            viewTransactions.SetColumnError(null, "Cannot commit this transaction into server.");
                        }
                        //Truyền map accountId -> accountName, giúp xây dựng Field InvolvedAccount
                        tran.SetAccountList(accNames);
                        if (viewTransactions.IsFocusedView)
                        {
                            viewTransactions.CollapseAllDetails();
                            int rowHandle = viewTransactions.GetRowHandle(tranList.Count - 1);
                            viewTransactions.SetMasterRowExpanded(rowHandle, true);
                            viewTransactions.GetDetailView(rowHandle, 0).Focus();
                        }
                    }
                }
            }
        }

        private void viewTransDetails_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                if (XtraMessageBox.Show("Are you sure you want to delete this item ?", "Delete confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1) == System.Windows.Forms.DialogResult.Yes)
                {
                    GridView view = sender as GridView;
                    int[] indexes = view.GetSelectedRows();
                    if (indexes != null)
                    {
                        BindingList<TransactionItem> details = view.DataSource as BindingList<TransactionItem>;
                        DTOTransaction tran = view.SourceRow as DTOTransaction;
                        if (details != null)
                        {
                            using (AccountingServer.AccountingServicesClient client = GetServiceClient())
                            {
                                for (int i = 0; i < indexes.Length; i++)
                                {
                                    TransactionItem item = view.GetRow(indexes[i]) as TransactionItem;
                                    if (item != null)
                                    {
                                        details.Remove(item);
                                    }
                                }
                            }
                            tran.Details = details.ToList();
                            RevalidateTransaction(view);
                        }
                    }
                }
            }
        }

        private void viewTransactions_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                if (XtraMessageBox.Show("Are you sure you want to delete this transaction ?", "Delete confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1) == System.Windows.Forms.DialogResult.Yes)
                {
                    GridView view = sender as GridView;
                    int[] indexes = view.GetSelectedRows();
                    if (indexes != null)
                    {

                        using (AccountingServer.AccountingServicesClient client = GetServiceClient())
                        {
                            for (int i = 0; i < indexes.Length; i++)
                            {
                                DTOTransaction tran = view.GetRow(indexes[i]) as DTOTransaction;
                                if (tran != null)
                                {
                                    string result = client.RemoveTransaction(tran.Id);
                                    if (result == null)
                                    {
                                        view.DeleteRow(indexes[i]);
                                    }
                                    else
                                    {
                                        var userChoice = XtraMessageBox.Show(result, "Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                                        switch (userChoice)
                                        {
                                            case DialogResult.Abort:
                                                i = indexes.Length;
                                                break;
                                            case DialogResult.Ignore:
                                                break;
                                            case DialogResult.Retry:
                                                i--;
                                                continue;
                                            default:
                                                break;
                                        }
                                    }
                                }
                            }
                        }

                    }
                }
            }
        }

        private void viewTransactions_FocusedColumnChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedColumnChangedEventArgs e)
        {
            viewTransactions.OptionsNavigation.UseTabKey = true;
            if (viewTransactions.IsNewItemRow(viewTransactions.FocusedRowHandle))
            {
                if (e.FocusedColumn == colAmount)
                {
                    viewTransactions.OptionsNavigation.UseTabKey = false;
                }
            }
        }

        private void iNew_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            viewTransactions.AddNewRow();
            viewTransactions.Focus();
            viewTransactions.FocusedColumn = colDate;
        }

        private void GetAccountActivitiesData()
        {
            if (activitiesDateFrom.EditValue == null || activitiesDateTo.EditValue == null)
            {
                return;
            }
            DateTime fromDate = (DateTime)activitiesDateFrom.EditValue;
            DateTime toDate = (DateTime)activitiesDateTo.EditValue;
            if (fromDate > toDate)
            {
                return;
            }
            List<int> ids = new List<int>();
            foreach (DevExpress.XtraEditors.Controls.CheckedListBoxItem item in cbActivitiesAccounts.Properties.Items)
            {
                if (item.CheckState == CheckState.Checked && item.Value is DTOAccount)
                {
                    ids.Add(((DTOAccount)item.Value).Id);
                }
            }
            if (ids.Count > 0)
            {
                using (AccountingServer.AccountingServicesClient client = GetServiceClient())
                {
                    List<DTOAccountActivity> data = client.GetAccountActivities(ids, fromDate, toDate);
                    DateTime lastDate = fromDate.Date.AddDays(-1);
                    if (cbActivitiesBeginningBalance.Checked)
                    {
                        decimal beginningBalance = client.GetBalance(ids, lastDate);
                        data.Insert(0, new DTOAccountActivity()
                        {
                            TransactionId = 0,
                            Explaination = "Beginning Balance",
                            Date = lastDate,
                            Debit = beginningBalance > 0 ? beginningBalance : 0,
                            Credit = beginningBalance < 0 ? -beginningBalance : 0
                        });
                    }
                    gridAccountActivities.DataSource = data;
                }
            }
        }

        private void GetAccountSummaryData()
        {
            if (disableGetSummary)
            {
                return;
            }
            if (summaryDateFrom.EditValue == null || summaryDateTo.EditValue == null)
            {
                return;
            }
            DateTime fromDate = (DateTime)summaryDateFrom.EditValue;
            DateTime toDate = (DateTime)summaryDateTo.EditValue;
            fromDate = new DateTime(fromDate.Year, fromDate.Month, 1);
            toDate = new DateTime(toDate.Year, toDate.Month, 1);
            if (fromDate > toDate)
            {
                return;
            }
            List<int> ids = new List<int>();
            foreach (DevExpress.XtraEditors.Controls.CheckedListBoxItem item in cbSummaryAccounts.Properties.Items)
            {
                if (item.CheckState == CheckState.Checked && item.Value is DTOAccount)
                {
                    ids.Add(((DTOAccount)item.Value).Id);
                }
            }
            if (ids.Count > 0)
            {
                List<DateTime> points = new List<DateTime>();
                DateTime d = fromDate;
                while (d <= toDate)
                {
                    points.Add(d);
                    d = d.AddMonths(1);
                }
                points.Add(d);
                using (AccountingServer.AccountingServicesClient client = GetServiceClient())
                {
                    List<DTOAccountSummary> data = client.GetAccountSummaries(ids, points);
                    DataTable displayData = new DataTable("AccountSummaries");
                    viewAccountSummary.Columns.Clear();

                    displayData.Columns.Add("Id", typeof(int)).Caption = "Id";
                    displayData.Columns.Add("AccountName", typeof(string)).Caption = "Account Name";

                    viewAccountSummary.Columns.AddField("Id").Visible = false;
                    var accNameCol = viewAccountSummary.Columns.AddField("AccountName");
                    accNameCol.OptionsFilter.FilterPopupMode = DevExpress.XtraGrid.Columns.FilterPopupMode.CheckedList;
                    accNameCol.Visible = true;
                    if (chkSummaryBeginningBalance.Checked)
                    {
                        foreach (var point in points)
                        {
                            var col = displayData.Columns.Add(point.ToString("MMyyyy"), typeof(decimal));
                            col.Caption = point.ToString("dd/MM/yyyy");

                            var discol = viewAccountSummary.Columns.AddField(point.ToString("MMyyyy"));
                            discol.ColumnEdit = MoneyVND;
                            discol.SummaryItem.FieldName = point.ToString("MMyyyy");
                            discol.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum;
                            discol.SummaryItem.DisplayFormat = "{0:0,0} đ";
                            discol.Visible = true;
                        }

                        foreach (var item in data)
                        {
                            bool display = false;
                            object[] values = new object[displayData.Columns.Count];
                            values[0] = item.AccountId;
                            values[1] = accNames[item.AccountId];
                            for (int i = 2; i < values.Length; i++)
                            {
                                values[i] = item.Balances[i - 2].Balance;
                                if (item.Balances[i - 2].Balance != 0)
                                {
                                    display = true;
                                }
                            }
                            if (display)
                            {
                                displayData.Rows.Add(values); 
                            }
                        }
                    }
                    else
                    {
                        points.Remove(d);
                        foreach (var point in points)
                        {
                            var col = displayData.Columns.Add(point.ToString("MMyyyy"), typeof(decimal));
                            col.Caption = point.ToString("MM/yyyy");

                            var discol = viewAccountSummary.Columns.AddField(point.ToString("MMyyyy"));
                            discol.ColumnEdit = MoneyVND;
                            discol.SummaryItem.FieldName = point.ToString("MMyyyy");
                            discol.SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum;
                            discol.SummaryItem.DisplayFormat = "{0:0,0} đ";
                            discol.Visible = true;
                        }

                        foreach (var item in data)
                        {
                            bool display = false;
                            object[] values = new object[displayData.Columns.Count];
                            values[0] = item.AccountId;
                            values[1] = accNames[item.AccountId];
                            for (int i = 2; i < values.Length; i++)
                            {
                                values[i] = item.Balances[i - 1].Balance - item.Balances[i - 2].Balance;
                                if ((decimal)values[i] != 0)
                                {
                                    display = true;
                                }
                            }
                            if (display)
                            {
                                displayData.Rows.Add(values); 
                            }
                        }
                    }
                    gridAccountSummary.DataSource = displayData;
                }
            }
        }

        private void dateFrom_EditValueChanged(object sender, EventArgs e)
        {
            GetAccountActivitiesData();
        }

        private void viewAccountActivities_CustomSummaryCalculate(object sender, DevExpress.Data.CustomSummaryEventArgs e)
        {
            switch (e.SummaryProcess)
            {
                case DevExpress.Data.CustomSummaryProcess.Calculate:
                    GridView view = sender as GridView;
                    if (view != null)
                    {
                        DTOAccountActivity data = view.GetRow(e.RowHandle) as DTOAccountActivity;
                        if (data != null)
                        {
                            e.TotalValue = (decimal)e.TotalValue + data.Debit - data.Credit;
                        }
                    }
                    break;
                case DevExpress.Data.CustomSummaryProcess.Finalize:
                    if (e.Item == colActivityDebit.SummaryItem)
                    {
                        if (e.TotalValue != null && (decimal)e.TotalValue < 0)
                        {
                            e.TotalValue = (decimal)0;
                        }
                    }
                    else if (e.Item == colActivityCredit.SummaryItem)
                    {
                        if (e.TotalValue != null)
                        {
                            if ((decimal)e.TotalValue < 0)
                            {
                                e.TotalValue = -(decimal)e.TotalValue;
                            }
                            else
                            {
                                e.TotalValue = (decimal)0;
                            }
                        }
                    }
                    break;
                case DevExpress.Data.CustomSummaryProcess.Start:
                    e.TotalValue = (decimal)0;
                    break;
                default:
                    break;
            }
        }

        private void cbBeginningBalance_CheckedChanged(object sender, EventArgs e)
        {
            GetAccountActivitiesData();
        }

        private void viewAccountActivities_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
        {
            if (e.Column.FieldName == colActivityCredit.FieldName || e.Column.FieldName == colActivityDebit.FieldName)
            {
                if (e.Value != null && (decimal)e.Value == 0)
                {
                    e.DisplayText = "";
                }
            }
        }

        private void summaryDateFrom_EditValueChanged(object sender, EventArgs e)
        {
            GetAccountSummaryData();
        }

        private void journalDateFrom_EditValueChanged(object sender, EventArgs e)
        {
            LoadJournal();
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            accList.RaiseListChangedEvents = true;
            accList.ListChanged += (sender1, e1) =>
            {
                BuildAccoutNameDict(accList);
            };
            using (LoginDialog loginDlg = new LoginDialog())
            {
                loginDlg.Address = endpointAddress;
                bool ok = false;
                while (!ok)
                {
                    if (loginDlg.ShowDialog() == System.Windows.Forms.DialogResult.Cancel)
                    {
                        Application.Exit();
                        return;
                    }
                    username = loginDlg.UserName;
                    password = loginDlg.Password;
                    endpointAddress = loginDlg.Address;
                    ok = true;
                    AccountingServicesClient client = GetServiceClient();

                    try
                    {
                        client.GetServerTime();
                    }
                    catch (System.ServiceModel.Security.MessageSecurityException ex)
                    {
                        ok = false;
                        XtraMessageBox.Show("Username or password is incorrect.", "Security Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                    }
                    catch (System.ServiceModel.EndpointNotFoundException ex)
                    {
                        ok = false;
                        XtraMessageBox.Show("Server address not found.", "Server not found", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                    }
                    finally
                    {
                        try
                        {
                            client.Close();
                        }
                        catch (Exception ex)
                        {
                        }
                    }

                }
            }

            journalDateFrom.EditValue = DateTime.Today.AddMonths(-1);
            journalDateTo.EditValue = DateTime.Today;
            //LoadJournal();
            activitiesDateFrom.EditValue = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
            activitiesDateTo.EditValue = DateTime.Now.Date;
            cbActivitiesAccounts.Properties.DataSource = accList;
            cbSummaryAccounts.Properties.DataSource = accList;
        }

        private void LoadSummaryForAccountSet(Func<DTOAccount, bool> selector)
        {
            cbSummaryAccounts.RefreshEditValue();
            try
            {
                disableGetSummary = true;
                cbSummaryAccounts.Properties.LockEvents();
                foreach (DevExpress.XtraEditors.Controls.CheckedListBoxItem item in cbSummaryAccounts.Properties.Items)
                {
                    if (item.Value is DTOAccount)
                    {
                        DTOAccount acc = item.Value as DTOAccount;
                        if (selector.Invoke(acc))
                        {
                            item.CheckState = CheckState.Checked;
                        }
                        else
                        {
                            item.CheckState = CheckState.Unchecked;
                        }
                    }
                }
            }
            finally
            {
                disableGetSummary = false;
                cbSummaryAccounts.Properties.UnLockEvents();
                GetAccountSummaryData();
            }
        }
        private void btnTotalAssets_Click(object sender, EventArgs e)
        {
            LoadSummaryForAccountSet(i => i.AccountName.StartsWith("1"));
        }

        private void btnCurrentAssets_Click(object sender, EventArgs e)
        {
            LoadSummaryForAccountSet(i => i.AccountName.StartsWith("10"));
        }

        private void btnTotalExpenses_Click(object sender, EventArgs e)
        {
            LoadSummaryForAccountSet(i => i.AccountName.StartsWith("5") || i.AccountName.StartsWith("6"));
        }

        private void btnCoreExpenses_Click(object sender, EventArgs e)
        {
            LoadSummaryForAccountSet(i => i.AccountName.StartsWith("5"));
        }
    }
}